/**
 * 命令模式
 */

interface ICommand {
    execute(): void;
    // 撤销
    undo(): void;
}
// 大门类
class Door {
    openDoor() {
        console.log('门打开了');
    }
    closeDoor() {
        console.log('门关闭了');
    }
}
// 电灯类
class Light {
    lightOn() {
        console.log('打开了电灯');
    }
    lightOff() {
        console.log('关闭了电灯');
    }
}
class Tv {
    TurnOnTv() {
        console.log('电视打开了');
    }
    TurnOffTv() {
        console.log('电视关闭了');
    }
}
class Music {
    play() {
        console.log('开始播放音乐');
    }
    stop() {
        console.log('停止播放音乐');
    }
}
// 开门命令
class DoorOpenCommand implements ICommand {
    private door: Door | undefined;

    setDoor(door: Door) {
        this.door = door;
    }
    execute() {
        this.door?.openDoor();
    }
    undo() {
        this.door?.closeDoor();
    }
}
// 关门命令
class DoorCloseCommand implements ICommand {
    private door: Door | undefined;

    setDoor(door: Door) {
        this.door = door;
    }
    execute() {
        this.door?.closeDoor();
    }
    undo() {
        this.door?.openDoor();
    }
}
// 开灯命令
class LightOnCommand implements ICommand {
    private light: Light | undefined;

    setLight(light: Light) {
        this.light = light;
    }
    execute() {
        this.light?.lightOn();
    }
    undo() {
        this.light?.lightOff();
    }
}
// 关灯命令
class LightOffCommand implements ICommand {
    private light: Light | undefined;

    setLight(light: Light) {
        this.light = light;
    }
    execute() {
        this.light?.lightOff();
    }
    undo() {
        this.light?.lightOn();
    }
}
// 电视、音乐的命令类似。

// 可以看到，我们将家居控制的代码转移到了命令类中，当命令执行时，调用对应家具的 API 实现开启或关闭。

// 初始化智能家居
const door = new Door();
const light = new Light();
const tv = new Tv();
const music = new Music();
// 初始化命令
const doorOpenCommand = new DoorOpenCommand();
const doorCloseCommand = new DoorCloseCommand();
doorOpenCommand.setDoor(door);
doorCloseCommand.setDoor(door);
const lightOnCommand = new LightOnCommand();
const lightOffCommand = new LightOffCommand();
lightOnCommand.setLight(light);
lightOffCommand.setLight(light);
// 已输入的命令
const commands: ICommand[] = [];

const handleCommand = (isChecked: boolean, openCommand: ICommand, closeCommand: ICommand) => {
    if (isChecked) {
        commands.push(openCommand);
        openCommand.execute();
    } else {
        commands.push(closeCommand);
        closeCommand.execute();
    }
};
// 与ui绑定的伪代码
// // 大门开关遥控
// switchDoor.setOnCheckedChangeListener((view, isChecked) -> {
//     handleCommand(isChecked, doorOpenCommand, doorCloseCommand);
// });
// // 电灯开关遥控
// switchLight.setOnCheckedChangeListener((view, isChecked) -> {
//     handleCommand(isChecked, lightOnCommand, lightOffCommand);
// });
// // 电视开关遥控
// switchTv.setOnCheckedChangeListener((view, isChecked) -> {
//     handleCommand(isChecked, turnOnTvCommand, turnOffTvCommand);
// });
// // 音乐开关遥控
// switchMusic.setOnCheckedChangeListener((view, isChecked) -> {
//     handleCommand(isChecked, musicPlayCommand, musicStopCommand);
// });

// 撤销按钮
//   btnUndo.setOnClickListener(view -> {
//     if (commands.length === 0) return;
//     // 撤销上一个命令
//     const lastCommand = commands.pop();
//     lastCommand.undo();
// });

// -- 宏命令
// 接下来我们给遥控器添加一个 “睡眠” 按钮，按下时可以一键关闭大门，关闭电灯，关闭电视、打开音乐
class MacroCommand implements ICommand {
    // 定义一组命令
    commands: ICommand[];
    constructor(commands: ICommand[]) {
        this.commands = commands;
    }
    execute() {
        // 宏命令执行时，每个命令依次执行
        for (let i = 0; i < commands.length; i++) {
            commands[i].execute();
        }
    }
    undo() {
        // 宏命令撤销时，每个命令依次撤销
        for (let i = 0; i < commands.length; i++) {
            commands[i].undo();
        }
    }
}

// // 定义睡眠宏命令
const sleepCommand = new MacroCommand([
    doorCloseCommand,
    lightOffCommand,
    // turnOffTvCommand,
    // musicPlayCommand,
]);
// // 睡眠按钮
// btnSleep.setOnClickListener(view -> {
//     // 将执行的命令保存到栈中，以便撤销
//     commands.push(sleepCommand);
//     // 执行睡眠命令
//     sleepCommand.execute();
// });

// 命令模式的主要优点如下：

// 降低系统的耦合度。将 “行为请求者” 和 ”行为实现者“ 解耦。
// 扩展性强。增加或删除命令非常方便，并且不会影响其他类。
// 封装 “方法调用”，方便实现 Undo 和 Redo 操作。
// 灵活性强，可以实现宏命令。
// 它的主要缺点是：

// 会产生大量命令类。增加了系统的复杂性。
